﻿using Furion.FriendlyException;
using Furion.VirtualFileServer;
using JinianNet.JNTemplate;
using Microsoft.Extensions.FileProviders;
using Photo.Application.System.BuildCode.Dto;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

namespace Photo.Application.System.CodeBuild
{
    /// <summary>
    /// 系统代码生成器
    /// </summary>
    [ApiDescriptionSettings(ApiGroupConsts.System, Module = ApiGroupConsts.System)]
    [AllowAnonymous]
    public class BuildCodeService : IDynamicApiController
    {
        private readonly ISqlSugarClient _db;
        public BuildCodeService(ISqlSugarClient db)
        {
            _db = db;
        }

        /// <summary>
        /// 获取模块列表
        /// </summary>
        /// <returns></returns>
        public List<KeyValueDto> GetModuleList()
        {
            var list = typeof(ApiGroupConsts).GetFields().Where(o => o.FieldType == typeof(string))
                .Select(o => new KeyValueDto
                {
                    Key = o.Name,
                    Value = o.Name,
                    Description = o.Name
                })
                .ToList();
            return list;
        }

        /// <summary>
        /// 查询数据库表列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public List<DbTableInfo> GetTableList(BaseInput input)
        {
            var list = _db.DbMaintenance.GetTableInfoList(false)
                .Where(o => o.DbObjectType == DbObjectType.Table)
                .WhereIF(!string.IsNullOrWhiteSpace(input.Content), o => o.Name.Contains(input.Content) || o.Description.Contains(input.Content))
                .ToList();

            return list;
        }

        /// <summary>
        /// 获取表字段列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public List<DbColumnInfo> GetColumnList(BaseInput input)
        {
            var list = _db.DbMaintenance.GetColumnInfosByTableName(input.Content, false);

            return list;
        }

        /// <summary>
        /// 构建代码预览
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<string> BuildCodePreview(BuildCodeInput input)
        {
            //1.读取表信息
            var tableInfo = _db.DbMaintenance.GetTableInfoList(false)
                .Where(o => o.DbObjectType == DbObjectType.Table)
                .Where(o => o.Name == input.TableName)
                .FirstOrDefault();
            if (tableInfo == null)
                throw Oops.Oh("当前表不存在");

            //2.读取表字段信息
            var baseColumnList = typeof(BaseEntity).GetProperties().Select(o => o.Name).ToList();
            var tableColumnList = _db.DbMaintenance.GetColumnInfosByTableName(input.TableName, false).FindAll(o => !baseColumnList.Contains(o.DbColumnName))
                .Select(o => new TableColumnDto
                {
                    DbColumnName = o.DbColumnName,
                    ColumnDescription = o.ColumnDescription,
                    DataType = o.DataType,
                    IsNullable = o.IsNullable,
                }).ToList();

            //3.解析模板代码
            var fileProvider = FS.GetEmbeddedFileProvider(Assembly.Load("Photo.Core"));
            byte[] buffer;
            using (Stream readStream = fileProvider.GetFileInfo("BuildCodeTemplate.Entity.txt").CreateReadStream())
            {
                buffer = new byte[readStream.Length];
                await readStream.ReadAsync(buffer.AsMemory(0, buffer.Length));
            }
            var content = Encoding.UTF8.GetString(buffer);

            //4.构建实体类代码
            var template = Engine.CreateTemplate(content);

            template.Set("ModuleName", input.ModuleName);
            template.Set("TableName", tableInfo.Name);
            template.Set("TableDescription", tableInfo.Description);
            template.Set("Author", input.Author);
            template.Set("NowTime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            template.Set("EntityName", input.EntityName);
            template.Set("ColumnList", tableColumnList);

            var result = template.Render();

            return result;
        }



    }
}
